1 /* 2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021 3 License: [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the CC BY-4.0 License. 8 (See accompanying file LICENSE.txt or copy at 9 https://creativecommons.org/licenses/by/4.0/ 10 */ 11 module hip.systems.hotload; 12 13 version(Load_DScript): 14 import std.file : copy, rename; 15 import hip.filesystem.hipfs; 16 import hip.util.system; 17 import hip.util.path; 18 import hip.console.log; 19 import hip.error.handler; 20 21 class HotloadableDLL 22 { 23 void* lib; 24 25 immutable string trueLibPath; 26 void delegate (void* libPointer) onDllLoad; 27 string tempDll; 28 string tempPdb; 29 this(string path, void delegate (void* libPointer) onDllLoad) 30 { 31 ErrorHandler.assertExit(path != null, "DLL path should not be null: 32 Call `dub -c script -- path/to/project` dub -c script requires that argument."); 33 34 import std.path; 35 path = absolutePath(path).buildNormalizedPath; 36 if(HipFS.absoluteIsDir(path)) 37 path = joinPath(path, path.filenameNoExt); 38 if(!dynamicLibraryIsLibNameValid(path)) 39 path = dynamicLibraryGetLibName(path); 40 trueLibPath = path; 41 this.onDllLoad = onDllLoad; 42 load(path); 43 } 44 protected bool load(string path) 45 { 46 import std.file; 47 if(!HipFS.absoluteExists(path)) 48 { 49 import hip.console.log; 50 logln("Does not exists ", path); 51 return false; 52 } 53 //Create dll_hiptempdll 54 tempDll = getTempName(path); 55 copy(path, tempDll); 56 57 // version(Windows) 58 // {{ 59 // import std.process:executeShell; 60 // import hip.util.path; 61 // string tempDirectory = joinPath(path.dirName, "temp"); 62 // mkdirRecurse(tempDirectory); 63 64 // string thePdb = path.extension("pdb"); 65 // tempPdb = getTempName(thePdb); 66 // if(exists(thePdb)) 67 // { 68 // copy(thePdb, joinPath(tempDirectory, thePdb.baseName)); 69 // rename(thePdb, tempPdb); 70 // } 71 72 // }} 73 74 75 loglnInfo("Loading dll ", path); 76 lib = dynamicLibraryLoad(tempDll); 77 if(onDllLoad && lib != null) 78 onDllLoad(lib); 79 else if(lib == null) 80 loglnError("Could not load dll ", path); 81 return lib != null; 82 } 83 /** 84 * 85 * Params: 86 * path = File path 87 * Returns: filePath.(ext)_hiptempdll 88 */ 89 static string getTempName(string path) 90 { 91 import hip.util.string; 92 string d = dirName(path); 93 string n = baseName(path); 94 string ext = extension(n); 95 96 int ind = lastIndexOf(n, "_hiptemp"); 97 if(ind != -1) 98 return path; 99 return joinPath(d, n[0..$-(ext.length+1)]~"_hiptemp."~ext); 100 } 101 102 void reload() 103 { 104 if(lib != null) 105 { 106 dynamicLibraryRelease(lib); 107 lib = null; 108 } 109 load(trueLibPath); 110 } 111 112 void dispose() 113 { 114 import hip.error.handler; 115 if(lib != null) 116 { 117 if(!dynamicLibraryRelease(lib)) 118 return ErrorHandler.showErrorMessage("Could not unload the dll ", tempDll); 119 120 foreach(remFile; [tempDll, tempPdb]) 121 if(remFile && !HipFS.absoluteRemove(remFile)) 122 { 123 ErrorHandler.showErrorMessage("Could not remove ", remFile); 124 } 125 } 126 } 127 }